using System;
using System.Collections.Generic;
using System.Text;
using DCRF.Common.Helper;
using DCRF.Common.Primitive;
using DCRF.Common.Collection;
using System.Collections;
using DCRF.Common.Core;
using DCRF.Common.Definition;
using DCRF.Common.Connection;
using NetSockets.Peer;
using DCRF.Common.Support;

namespace DCRF.Common.Interface
{
    public delegate void RequestCallbackDelegate(object tag, object result);

    /// <summary>
    /// </summary>
    public interface IBlockWeb: IDisposable
    {
        /// <summary>
        ///// A list of Guids of blocks loaded in this web.
        ///// </summary>
        IList<Guid> BlockHandles
        {
            get;
        }

        /// <summary>
        /// Sometimes some blocks need to make a decision according to identifier of another block from which there is only
        /// a Guid.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        CID GetBlockId(Guid id);

        /// <summary>
        /// Number of blocks in this web.
        ///// </summary>
        int BlockCount
        {
            get;
        }

        object GetBlockWebMetaInfo(BlockWebMetaInfoType type, string itemName);


        /// <summary>
        /// This methods uses broker to create a new instance of a block with given CID.
        /// We need metadata when adding a Block. This can be used to find alternative Blocks
        /// at BlockWeb level on-demand. For example instead of 1.0.0.0 we may have only 1.0.0.3 of the same Block
        /// as an alternative.
        /// </summary>
        /// <returns></returns>
        Guid AddBlock(CID id);

        /// <summary>
        /// Delete a block from blocks loaded in the web.
        /// </summary>
        /// <param name="handle"></param>
        void DeleteBlock(Guid handle); 

        /// <summary>
        /// As we do not like to pass IBlock object to requesters, we have a wrapper for IBlock methods
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        IBlock this[Guid handle]
        {
            get;
        }

        IGlobalConnector this[string key]
        {
            get;
        }


        /// <summary>
        /// Returns address of this web. Other webs can connect to this blockWeb using this address
        /// </summary>
        string Address
        {
            get;
        }

        /// <summary>
        /// This method looks into Blocks in the BlockWeb that have exact same version,id,product which is specified by handle
        /// there may be many because it may be multiple-instance
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        List<Guid> FindBlocks(CID handle);

        /// <summary>
        /// This methods searches in BlockWeb's Blocks and returns a list of Block identifiers that
        /// have the given tag. This is used to have a grouping mechanism.
        /// </summary>
        /// <param name="tag"></param>
        /// <returns>A list of handles that can be used to target a specific block</returns>
        List<Guid> FindBlocks(string tag);

        string Id
        {
            get;
        }

        /// <summary>
        /// Connect to an external blockWeb
        /// TODO: add connect for IBlockWeb
        /// </summary>
        /// <param name="url"></param>
        bool Connect(string host, int port, string peerId);
        
        bool Connect(IBlockWeb web, string peerId);

        void Disconnect(string peerId);
        bool MigrateBlock(Guid guid, string peerId);

        IBlockWeb GetPeer(string peerId);

        void ReloadBlocks();

        event PeerConnectDelegate PeerConnected;
        event PeerConnectDelegate PeerDisconnected;
    }
}
